
import{ 
    startTagOpenRE
    ,attributeRe
    ,startTagCloseRe,
    endTagRe
} from './re-const';
import {ElementNode,StackNode,AttributeKV} from './element-node'
export class TagParser{
    constructor(){
        this.stack=new Array<StackNode>();
    }
    private parent:ElementNode;
    private last:ElementNode;
    private root:ElementNode;
    private html:string;
    private stack:StackNode[];
    private index:number=0;
    private lastTag:string;
    private getAElement(ele:ElementNode){
        console.log(ele)
    }
    private advance(num:number){
        this.index+=num;
        this.html=this.html.substr(num);
    }
    private parseStartTag():ElementNode{
            let start=this.html.match(startTagOpenRE);
            if(start){
                //处理标签名
                let tagName=start[1];
                var tag=new ElementNode(tagName,this.index);
                this.advance(start[0].length);
                //处理属性
                let end, attr;
                let attrs=[];
                while(!(end=this.html.match(startTagCloseRe))&&(attr=this.html.match(attributeRe))){
                    attrs.push(attr);
                     this.advance(attr[0].length);
                }
                if(end){
                    tag.unarySlash=end[1];
                    this.advance(end[0].length);
                    tag.end=this.index;
                    tag.attrs=attrs;
                }
            }
            return tag;

    }
    private getAStartElement(tagName:string, attrs:{name:string;value:string}[],isSelfClose:boolean, start:number, end:number){
        console.log(arguments);
    }
    private getAEndElement(tagName:string,start:number,end:number){
        console.log(arguments);
    }
    private handleChar(text:string){
        console.log(`捕获到字符串:${text}`);
    }
    private handleStartTag(tag:ElementNode){
       let lowerTagName=tag.name.toLowerCase();
       let isSelfClose=!tag.unarySlash;
       let i=tag.attrs.length;
       let attrs=new Array(i);
       for(let m=0;m<i;m++){
           let args=tag.attrs[m];
           const value = args[3] || args[4] || args[5] || ''
           attrs[i]={
             name:args[1],
             value:value
           }
       }
        if (!isSelfClose) {
            this.stack.push({ tag:lowerTagName, attrs: attrs });
            this.lastTag = lowerTagName;
        }
        this.getAStartElement(lowerTagName,attrs,isSelfClose,tag.start,tag.end);
    }
    /**
     * 分析闭标签
     * @param  {string} tagName 闭标签的标签名
     * @param  {number} start 闭标签的开始位置
     * @param  {number} end 闭标签的结束位置
     */
    private parseEndTag(tagName:string,start?:number,end?:number){
        if(start==null)start=this.index;
        if(end===null)end=this.index;
        let lowerTagName:string,pos:number;
        if(tagName){
            lowerTagName=tagName.toLowerCase();
            for(pos=this.stack.length-1;pos>=0;pos--){
                if(this.stack[pos].tag===lowerTagName){
                    break;
                }
            }
        }else{
            pos=0;
        }
        if(pos>=0){
            //进行出栈
            for(let i=this.stack.length-1;i>=pos;i--){
                this.getAEndElement(this.stack[i].tag,start,end);
            }
        }
        
    }
    public  parseHtml(htmlsr:string){
        htmlsr=htmlsr.trim();
        this.html=htmlsr;
        while(this.html){
        /**
         * 1.判断开头是否是“<”，
         * 2.如果是，则处理标签，处理属性
         * 3.如果不是，则说明是文本，则进行处理
         */
         if(this.html.indexOf("<")==0){
             //处理标签的闭标签
            let endMatcher=this.html.match(endTagRe);
            if(endMatcher){
                //TODO: 处理标签尾部
                let curIndex=this.index;//记录尾部标签的起始位置
                this.advance(endMatcher[0].length);
                this.parseEndTag(endMatcher[1],curIndex,this.index);
                continue;
            }
            const startTagMatch= this.parseStartTag();
            if(startTagMatch){
                this.handleStartTag(startTagMatch);
                continue
            }
            
         }else{
            let charpos=this.html.indexOf("<");
            if(charpos>=0){
                let char=this.html.substr(0,charpos);
                this.advance(charpos);
                this.handleChar(char);
            }else{
                break;
            }
            continue;
         }
         
        }
        
    }
}